package com.hotspot.chartview.view;

import java.util.ArrayList;
import java.util.List;

import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.Paint.FontMetricsInt;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;

import com.hotspot.chartview.R;
import com.hotspot.chartview.model.ColoredBarChartData;

/**
 * 自定义带颜色的柱状图
 * 
 * @author BaiYuliang
 * 
 */
public class ColoredBarChart extends View implements AnimatorUpdateListener {

    private static final String TAG = "ColoredBarChart";

    /**
     * 从xml中读取到的属性
     */
    private int mVisibleColumnNum; // 可见柱状图个数
    private int mCellWidth; // 单元格宽度
    private int mCellHeight; // 单元格高度
    private int mBarColor; // 柱状图颜色
    private int mTopTextColor; // 柱状图顶部标题颜色
    private int mTopTextSize; // 柱状图顶部字体大小
    private int mDividerColor; // 分割线颜色
    private int mTitleTextColor; // 底部字体颜色
    private int mTitleTextSize; // 底部字体大小

    /**
     * 画笔
     */
    private Paint mPaintTopText; // 柱状图顶部标题使用的画笔
    private Paint mPaintBar; // 柱状图使用的画笔
    private Paint mPaintDivider; // 分割线使用的画笔
    private Paint mPaintTitleText; // 柱状图底部文字使用的画笔

    private List<ColoredBarChartData> mColoredBarChartDatas;
    private int mBarViewHeight; // 报表的高度
    private float mDataMaxHeight; // 数据的最大值
    private int mBarWidth; // 柱状图宽度
    private int mDeltaX;
    private int mDeltaY;
    private int mBorderLeft;
    private int mBorderRight;

    /**
     * 动画
     */
    private float mPhaseX = 1f;
    private float mPhaseY = 1f;
    private ObjectAnimator mAnimatorX;
    private ObjectAnimator mAnimatorY;

    private int mLastTouchX; // 点击位置的X坐标
    private int mLastTouchY; // 点击位置的Y坐标
    private int mTouchSlop; // 滑动距离的阈值

    public ColoredBarChart(Context context) {
        this(context, null, 0);
    }

    public ColoredBarChart(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ColoredBarChart(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        if (attrs != null) {
            Resources resources = getResources();
            TypedArray typedArray = context.obtainStyledAttributes(attrs,
                    R.styleable.ColoredBarChart);
            mVisibleColumnNum = typedArray.getInteger(
                    R.styleable.ColoredBarChart_visible_column_num, 0);
            mCellWidth = typedArray
                    .getDimensionPixelSize(R.styleable.ColoredBarChart_cell_width, 0);
            mCellHeight = typedArray.getDimensionPixelSize(R.styleable.ColoredBarChart_cell_height,
                    0);
            mBarColor = typedArray.getColor(R.styleable.ColoredBarChart_bar_color,
                    resources.getColor(R.color.colored_bar_chart_bar_color_default));
            mTopTextColor = typedArray.getColor(R.styleable.ColoredBarChart_top_text_color,
                    resources.getColor(R.color.colored_bar_chart_top_text_color_default));
            mTopTextSize = typedArray.getDimensionPixelSize(
                    R.styleable.ColoredBarChart_top_text_size, 27);
            mDividerColor = typedArray.getColor(R.styleable.ColoredBarChart_divider_color,
                    resources.getColor(R.color.colored_bar_chart_divider_color_default));
            mTitleTextColor = typedArray.getColor(R.styleable.ColoredBarChart_title_text_color,
                    resources.getColor(R.color.colored_bar_chart_title_text_color_default));
            mTitleTextSize = typedArray.getDimensionPixelSize(
                    R.styleable.ColoredBarChart_title_text_size, 27);
            typedArray.recycle();
        }

        init(context); // 初始化参数
    }

    /**
     * 初始化参数
     * 
     * @param context
     *            上下文
     */
    private void init(Context context) {
        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
        mColoredBarChartDatas = new ArrayList<ColoredBarChartData>();

        /**
         * 柱状图顶部标题使用的画笔
         */
        mPaintTopText = new Paint();
        mPaintTopText.setColor(mTopTextColor);
        mPaintTopText.setTextSize(mTopTextSize);
        mPaintTopText.setTextAlign(Align.CENTER);
        mPaintTopText.setAntiAlias(true);

        /**
         * 柱状图使用的画笔
         */
        mPaintBar = new Paint();
        mPaintBar.setColor(mBarColor);

        /**
         * 创建画底部分割线用的画笔
         */
        mPaintDivider = new Paint();
        mPaintDivider.setColor(mDividerColor);
        mPaintDivider.setStrokeWidth(1);
        mPaintDivider.setAntiAlias(true);

        /**
         * 柱状图底部文字使用的画笔
         */
        mPaintTitleText = new Paint();
        mPaintTitleText.setColor(mTitleTextColor);
        mPaintTitleText.setTextSize(mTitleTextSize);
        mPaintTitleText.setTextAlign(Align.CENTER);
        mPaintTitleText.setAntiAlias(true);
    }

    /**
     * 初始化单元格的大小和位置
     */
    private void initCellSizeAndPosition() {
        int width = getMeasuredWidth();
        int height = getMeasuredHeight();
        if (mCellWidth == 0 && mVisibleColumnNum != 0) {
            mCellWidth = width / mVisibleColumnNum;
        }

        int dataSize = mColoredBarChartDatas.size();
        if (dataSize > 0) {
            if (mCellWidth == 0) {
                mCellWidth = width / dataSize;
            }
            if (mCellHeight == 0) {
                mCellHeight = height / dataSize;
            }
        }

        if (mVisibleColumnNum != 0) {
            if (dataSize < mVisibleColumnNum) {
                mBorderLeft = (width - mCellWidth * dataSize) / 2;
            } else if (dataSize > mVisibleColumnNum) {
                mCellWidth = (int) (width / (mVisibleColumnNum + 0.5));
            }
        }

        mBarViewHeight = (int) (height * 0.7); // 折线图部分占View的7/10
        mDeltaX = mBarWidth = (int) (mCellWidth * 0.2);
        mDeltaY = mBarWidth * 2;

        if (mColoredBarChartDatas.size() > 0) {
            mBorderRight = mCellWidth * mColoredBarChartDatas.size();
        } else {
            mBorderRight = width;
        }

        /**
         * 内容的最大值
         */
        for (ColoredBarChartData coloredBarChartData : mColoredBarChartDatas) {
            if (coloredBarChartData.height >= mDataMaxHeight) {
                mDataMaxHeight = coloredBarChartData.height;
            }
        }
    }

    /**
     * 画柱状图
     * 
     * @param canvas
     *            画布
     */
    private void drawBar(Canvas canvas) {
        int textLeft = mBorderLeft;
        float barLeft = mBorderLeft + (mCellWidth - mBarWidth) / 2;
        float barBottom = mDeltaY + mBarViewHeight;
        for (ColoredBarChartData coloredBarChartData : mColoredBarChartDatas) {
            /**
             * 画柱状图
             */
            float barTop = 0;
            if (mDataMaxHeight == 0) {
                barTop = barBottom - 8;
            } else {
                barTop = mDeltaY + mBarViewHeight
                        * (1 - mPhaseY * coloredBarChartData.height / mDataMaxHeight);
            }
            mPaintBar.setColor(coloredBarChartData.color);
            canvas.drawRect(barLeft, barTop, barLeft + mBarWidth, barBottom, mPaintBar);

            /**
             * 在柱状图顶部画数值
             */
            int textBottom = (int) (barTop - 10);
            int textTop = (int) (textBottom - mPaintTopText.getTextSize());
            Rect targetRect = new Rect(textLeft, textTop, textLeft + mCellWidth, textBottom);
            FontMetricsInt fontMetrics = mPaintTopText.getFontMetricsInt();
            int baseLine = targetRect.top
                    + (targetRect.bottom - targetRect.top - fontMetrics.bottom + fontMetrics.top)
                    / 2 - fontMetrics.top;
            mPaintTopText.setColor(coloredBarChartData.color);
            canvas.drawText("" + coloredBarChartData.height, targetRect.centerX(), baseLine,
                    mPaintTopText);
            textLeft += mCellWidth;
            barLeft += mCellWidth;
        }
    }

    /**
     * 画底部文字
     * 
     * @param canvas
     *            画布
     */
    private void drawBottomText(Canvas canvas) {
        canvas.save();
        canvas.translate(0, mDeltaY + mBarViewHeight);
        canvas.drawLine(0, 0, getMeasuredWidth(), 0, mPaintDivider);

        /**
         * 画底部文字
         */
        int titleLeft = mBorderLeft;
        int titleTop = 10;
        int titleBottom = titleTop + (int) mPaintTitleText.getTextSize() + 10;
        for (int i = 0; i < mColoredBarChartDatas.size(); i++) {
            ColoredBarChartData coloredBarChartData = mColoredBarChartDatas.get(i);
            Rect targetRect = new Rect(titleLeft, titleTop, titleLeft + mCellWidth, titleBottom);
            FontMetricsInt fontMetrics = mPaintTitleText.getFontMetricsInt();
            int baseLine = targetRect.top
                    + (targetRect.bottom - targetRect.top - fontMetrics.bottom + fontMetrics.top)
                    / 2 - fontMetrics.top;
            canvas.drawText(coloredBarChartData.title, targetRect.centerX(), baseLine,
                    mPaintTitleText);
            titleLeft += mCellWidth;
        }
        canvas.restore();
    }

    /**
     * 是否可以滑动
     * 
     * @param event
     *            MotionEvent
     * @return true:可以滑动;false:不能滑动
     */
    private boolean canScroll(MotionEvent event) {
        int x = (int) event.getX();
        int y = (int) event.getY();
        if (event.getAction() == MotionEvent.ACTION_MOVE) {
            int deltaX = x - mLastTouchX;
            int deltaY = y - mLastTouchY;
            if (Math.abs(deltaX) > mTouchSlop && Math.abs(deltaX) > Math.abs(deltaY)) {
                return true;
            }
        }
        return false;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        initCellSizeAndPosition(); // 初始化单元格大小和初始位置
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        drawBar(canvas); // 画柱状图
        drawBottomText(canvas); // 画底部文字
    }

    @SuppressLint("ClickableViewAccessibility")
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (mColoredBarChartDatas.size() <= mVisibleColumnNum) {
            return super.onTouchEvent(event);
        }
        int x = (int) event.getX();
        int y = (int) event.getY();
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            mLastTouchX = x;
            mLastTouchY = y;
            return true;
        case MotionEvent.ACTION_MOVE:
            if (canScroll(event)) {
                mBorderLeft += (x - mLastTouchX);
                if (mBorderLeft >= 0) {
                    mBorderLeft = 0;
                }
                if (mBorderLeft <= getMeasuredWidth() - mBorderRight) {
                    mBorderLeft = getMeasuredWidth() - mBorderRight;
                }
                mLastTouchX = x;
                mLastTouchY = y;
                invalidate();
            }
            break;
        }
        return super.onTouchEvent(event);
    }

    @Override
    public void onAnimationUpdate(ValueAnimator valueAnimator) {
        invalidate();
    }

    /**
     * phaseX的setter方法，与ObjectAnimator配合使用
     * 
     * @param phaseX
     *            X轴动画完执行进度
     */
    public void setPhaseX(float phaseX) {
        mPhaseX = phaseX;
    }

    /**
     * phaseY的setter方法，与ObjectAnimator配合使用
     * 
     * @param phaseY
     *            Y轴动画执行进度
     */
    public void setPhaseY(float phaseY) {
        mPhaseY = phaseY;
    }

    /**
     * X轴执行动画
     * 
     * @param durationMillis
     *            执行动画的时间
     */
    public void animateX(int durationMillis) {
        mAnimatorX = ObjectAnimator.ofFloat(this, "phaseX", 0f, 1f);
        mAnimatorX.setDuration(durationMillis);
        mAnimatorX.addUpdateListener(this);
        mAnimatorX.start();
    }

    /**
     * Y轴执行动画
     * 
     * @param durationMillis
     *            执行动画的时间
     */
    public void animateY(int durationMillis) {
        mAnimatorY = ObjectAnimator.ofFloat(this, "phaseY", 0f, 1f);
        mAnimatorY.setDuration(durationMillis);
        mAnimatorY.addUpdateListener(this);
        mAnimatorY.start();
    }

    /**
     * 为柱状图填充内容
     * 
     * @param coloredBarChartDatas
     *            内容
     */
    public void setColoredBarChartData(List<ColoredBarChartData> coloredBarChartDatas) {
        mColoredBarChartDatas.clear();
        if (coloredBarChartDatas != null && coloredBarChartDatas.size() > 0) {
            mColoredBarChartDatas.addAll(coloredBarChartDatas);
        }
        mDataMaxHeight = 0;
        mBorderLeft = 0;
        initCellSizeAndPosition();
        invalidate();
    }

}
